#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<limits.h>

/*
 * Circular Queue
 * enqueue:
 *    tail -> head ( '->' means 'goes for, persue' )
 * dequeue:
 *	  head -> tail
 *
 * empty:
 *    head == tail
 * full:
 *    (tail+1)/QUEUE_SIZE == head
 */

#define Data_Type_Error_Return INT_MIN
typedef int Data_Type;
typedef struct CQ{
	int head;
	int tail;
	int q_size;
	Data_Type *data;
} CQueue;

CQueue *
create_cqueue(int size)
{
	CQueue *queue = (CQueue *)malloc(sizeof(CQueue));
	queue->head = 0;
	queue->tail = 0;
	queue->q_size = size;
	queue->data = (Data_Type *)calloc(size, sizeof(Data_Type));

	return queue;
}

void
destroy_cqueue(CQueue *queue)
{
	free(queue->data);
	free(queue);
	queue = NULL;
}

static int
empty(CQueue *queue)
{
	return (queue->head == queue->tail);
}

static int
full(CQueue *queue)
{
	return ((queue->tail + 1)%queue->q_size == queue->head);
}

void
enqueue(CQueue *queue, Data_Type value)
{
	if(full(queue))
		return;
	queue->data[queue->tail] = value;
	queue->tail = (queue->tail + 1)%queue->q_size;
}

Data_Type
dequeue(CQueue *queue)
{
	Data_Type rt;
	if(empty(queue)) {
		fprintf(stdout, "CQueue is Empty, dequeue failed.\n");
		rt = Data_Type_Error_Return;
	} else {
		rt = queue->data[queue->head];
		queue->head = (queue->head + 1)%queue->q_size;
	}
	return rt;
}

/* FOR TEST ONLY */
void 
print_elements_in_cqueue(CQueue *queue)
{
	int i;
	printf("HEAD: %d, TAIL: %d\n", queue->head, queue->tail);
	for(i=0; i<queue->q_size; i++)
		printf("%d\t", queue->data[i]);
	printf("\n");
}
